package com.dzpk.gameserver.util;

import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;

import java.io.*;
import java.net.URLDecoder;
import java.nio.ByteOrder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 
 * @author Somnus
 * 
 */
public class GameServerUtils {

    private final static Logger log = Logger.getLogger(GameServerUtils.class);

    private static String[] cs = new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
            "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i",
            "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };

    private static Random random = new Random();


    public static String randomNameSuf() {
        int strLen = randomOne2N(3);
        StringBuffer sb = new StringBuffer();
        for (int i = 1; i <= strLen; i++) {
            int idx = random.nextInt(cs.length);
            sb.append(cs[idx]);
        }
        return sb.toString();
    }


    /**
     * MD5 加密
     */
    public static String getMD5Str(String str) {
        MessageDigest messageDigest = null;

        try {
            messageDigest = MessageDigest.getInstance("MD5");

            messageDigest.reset();

            messageDigest.update(str.getBytes(GameServerConstants.DEFAULT_CHARSET));
        } catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException caught!");
            System.exit(-1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        byte[] byteArray = messageDigest.digest();

        StringBuffer md5StrBuff = new StringBuffer();

        for (int i = 0; i < byteArray.length; i++) {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
            else
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
        }

        return md5StrBuff.toString();
    }

    public static int getCurrentTime() {
        return (int) (System.currentTimeMillis() / 1000);
    }

    public static int getDayOfYear() {
        return Calendar.getInstance().get(Calendar.DAY_OF_YEAR);
    }

    public static int getCurrentYear() {
        return Calendar.getInstance().get(Calendar.YEAR);
    }

    /** 获取当前日期的上一年总天数 */
    public static int getChineseAllDayBeforeYear() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, Calendar.getInstance().get(Calendar.YEAR) - 1);
        cal.set(cal.get(Calendar.YEAR), 11, 31);
        return cal.get(Calendar.DAY_OF_YEAR);
    }

    /**
     * 获取当天剩余的时间(分钟)
     * 
     * @return
     */
    public static int getLeftMinuteOfDay() {
        Calendar c = Calendar.getInstance();
        int leftMinute = 12 * 60 - (c.get(Calendar.HOUR) * 60 + c.get(Calendar.MINUTE));
        if (c.get(Calendar.AM_PM) == 0) {
            leftMinute += 12 * 60;
        }
        return leftMinute;
    }

    /**
     * 周一为1
     * 
     * @return
     */
    public static int getDayOfWeek() {
        Calendar c = Calendar.getInstance();
        return c.get(Calendar.DAY_OF_WEEK) - 1;
    }

    public static class DateUtils {

        public static final String FMT_DATE = "yyyy.MM.dd";
        public static final String FMT_DATE_1 = "yyyy-MM-dd";
        public static final String FMT_DATE_TIME = "yyyy-MM-dd HH:mm:ss";
        public static final String PVP_DATE = "HH:mm";

        public static String fromTimeStamp2StringDate(long second) {
            SimpleDateFormat sdf = new SimpleDateFormat(FMT_DATE);
            return sdf.format(new Date(second * 1000));
        }

        public static String fromTimeStamp2StringDateTime(long second) {
            SimpleDateFormat sdf = new SimpleDateFormat(FMT_DATE_TIME);
            return sdf.format(new Date(second * 1000));
        }

        public static Date addSeconds(Date date, int second) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.add(Calendar.SECOND, second);
            return cal.getTime();
        }

        /**
         * 获取为大于当前时间的整点或者半点时间，忽略秒
         * 
         * @return
         */
        public static Date get0And30Time() {
            Calendar c = Calendar.getInstance();

            int minute = c.get(Calendar.MINUTE);

            if (minute >= 0 && minute < 30) {
                c.add(Calendar.MINUTE, 30 - minute);
            } else {
                c.add(Calendar.MINUTE, 60 - minute);
            }

            return c.getTime();
        }

        /** 根据当前时间获取下周一凌晨的时间 */
        public static Date getWeekMondayTime() {
            Calendar cal = Calendar.getInstance();
            int day = cal.get(Calendar.DAY_OF_WEEK);
            int hour = cal.get(Calendar.HOUR_OF_DAY);
            int minute = cal.get(Calendar.MINUTE);
            if (day == 1) {
                // 说明是周日
                minute = (24 - hour - 1) * 60 + (60 - minute);
            } else {
                minute = (7 - day + 1) * 24 * 60 + (24 - hour - 1) * 60 + (60 - minute);
            }
            cal.add(Calendar.MINUTE, minute);
            cal.set(Calendar.SECOND, 0);
            return cal.getTime();
        }

        /** 根据当前时间获取下次排行榜刷新的时间 */
        public static Date getRefreshRankingTime(int oneHour, int secondHour) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Calendar cal = Calendar.getInstance();
            int hour = cal.get(Calendar.HOUR_OF_DAY);
            String hourAndMinute = "";
            // 活动日期
            if (hour < oneHour) {
                hourAndMinute = oneHour + ":00";
            } else if (hour >= oneHour && hour < secondHour) {
                hourAndMinute = secondHour + ":00";
            } else {
                hourAndMinute = oneHour + ":00";
            }
            Date date;
            try {
                date = sdf.parse(getCurrentDate() + " " + hourAndMinute + ":01");
                // 如果已过活动日期的时间,则设置明天
                if (date.before(new Date())) {
                    return new Date(date.getTime() + 24 * 60 * 60 * 1000);
                } else {
                    // 如果
                    return date;
                }
            } catch (ParseException e) {
                e.printStackTrace();
                return new Date();
            }
        }

        /** 获取初始化称号时间 秒 */
        public static int getRefreshDesignaTime(int oneHour, int secondHour) {
            int allSecond = 0;
            Calendar cal = Calendar.getInstance();
            int hour = cal.get(Calendar.HOUR_OF_DAY);
            int minute = cal.get(Calendar.MINUTE);
            int second = cal.get(Calendar.SECOND);
            if (hour >= secondHour && hour < 24) {
                allSecond = GameServerUtils.getCurrentTime() - ((hour - secondHour) * 3600 + minute * 60 + second);
            } else if (hour >= 0 && hour < oneHour) {
                allSecond = GameServerUtils.getCurrentTime() - ((hour + 4) * 3600 + minute * 60 + second);
            } else {
                allSecond = GameServerUtils.getCurrentTime() - ((hour - oneHour) * 3600 + minute * 60 + second);
            }
            return allSecond;
        }

        /**
         * 获取为大于当前时间的整点时间
         * 
         * @return
         */
        public static Date get0Time() {
            Calendar c = Calendar.getInstance();

            int minute = c.get(Calendar.MINUTE);
            c.add(Calendar.MINUTE, 60 - minute);
            c.set(Calendar.SECOND, 0);
            return c.getTime();
        }

        /**
         * 获取为大于当前时间的整点时间1秒
         * 
         * @return
         */
        public static Date get01Time() {
            Calendar c = Calendar.getInstance();

            int minute = c.get(Calendar.MINUTE);
            c.add(Calendar.MINUTE, 60 - minute);
            c.set(Calendar.SECOND, 1);
            return c.getTime();
        }

        /**
         * 获取当前周为当年第几周,（周一为一周第一天）
         * 
         * @return
         */
        public static int getChineseWeekOfYear() {
            Calendar cal = Calendar.getInstance();
            cal.setFirstDayOfWeek(Calendar.MONDAY);
            return cal.get(Calendar.WEEK_OF_YEAR);
        }

        /**
         * 获取为大于当前时间的整点时间或半的1秒
         * 
         * @return
         */
        public static Date getHmTime() {
            Calendar c = Calendar.getInstance();

            int minute = c.get(Calendar.MINUTE);
            if (minute > 30) {
                c.add(Calendar.MINUTE, 60 - minute);
            } else {
                c.add(Calendar.MINUTE, 30 - minute);
            }
            c.set(Calendar.SECOND, 1);
            return c.getTime();
        }

        public static void main(String[] args) {
            StringBuffer sb = new StringBuffer();
            for (int i = 65; i < 91; i++) {
                sb.append("\"").append((char) i).append("\"").append(",");
            }

            for (int i = 97; i < 123; i++) {
                sb.append("\"").append((char) i).append("\"").append(",");
            }

            System.out.println(sb.toString());
            for (int i = 0; i < 100; i++) {
                System.out.println(randomNameSuf());
            }
        }

        // 获取第2天0点2分的时间
        public static Date get2Past0Time() {
            Calendar c = Calendar.getInstance();

            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 2);
            c.set(Calendar.SECOND, 0);
            c.add(Calendar.DATE, 1);
            return c.getTime();
        }

        // 获取第2天0点1分的时间
        public static Date get1Past0Time() {
            Calendar c = Calendar.getInstance();

            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 1);
            c.set(Calendar.SECOND, 0);
            c.add(Calendar.DATE, 1);
            return c.getTime();
        }

        // 获取当前小时的秒
        public static Date getCurrentHourSeconds() {
            Calendar c = Calendar.getInstance();
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 0);
            return c.getTime();
        }

        // 获取下一个是n倍数的小时
        public static Date getNextModNHourTime(int n) {
            Calendar c = Calendar.getInstance();
            c.add(Calendar.HOUR_OF_DAY, n - c.get(Calendar.HOUR_OF_DAY) % n);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 0);
            return c.getTime();
        }

        public static Date get2SecondPast0Time() {
            Calendar c = Calendar.getInstance();

            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 2);
            c.add(Calendar.DATE, 1);
            return c.getTime();
        }

        /** 获取下时刻的整点时间 */
        public static Date getNextHourTime() {
            Calendar c = Calendar.getInstance();
            c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + 1);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 0);
            return c.getTime();
        }

        // 获取第2天0点1分的时间
        public static Date getNextDayPastMinute(int minute) {
            Calendar c = Calendar.getInstance();

            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, minute);
            c.set(Calendar.SECOND, 0);
            c.add(Calendar.DATE, 1);
            return c.getTime();
        }

        // 获取当前时间
        public static String getCurrentTime() {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.format(new Date());
        }

        // 获取当前日期
        public static String getCurrentDate() {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.format(new Date());
        }

        // 获取当前日期转换成的秒数
        public static int getCurrentDateSeconds() {
            Calendar c = Calendar.getInstance();

            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 0);
            c.add(Calendar.DATE, 0);
            return (int) (c.getTime().getTime() / 1000);
        }

        // 获取两个以秒为单位的时间差(单位:天)
        public static int getDiffDay(int beforeDay, int afterDay) {
            int diffSeconds = afterDay - beforeDay;
            return diffSeconds / 60 / 60 / 24;
        }

        public static String getTomorrowDate() {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            Date dt = new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000);
            return sdf.format(dt);

        }

        public static String getCurrentHourAndMinute() {
            SimpleDateFormat sdf = new SimpleDateFormat("HHmm");
            return sdf.format(new Date());
        }

        public static int getCurrentIntHourAndMinute() {
            SimpleDateFormat sdf = new SimpleDateFormat("HHmm");
            return Integer.parseInt(sdf.format(new Date()));
        }

        /**
         * 获得当前日
         * 
         * @return
         */
        public static int getCurrentDay() {
            Calendar c = Calendar.getInstance();
            return c.get(Calendar.DATE);
        }

        public static String getYestesday() {
            Calendar c = Calendar.getInstance();
            c.add(Calendar.DATE, -1);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.format(c.getTime());
        }

        // 当天的0点1秒
        public static int getTodaySecond() {
            Calendar c = Calendar.getInstance();
            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 1);
            return (int) c.getTimeInMillis() / 1000;

        }

        /**
         * 通过格式，日期str获取秒
         * 
         * @param format
         * @param date
         * @return
         */
        public static int getSecondByDateStr(String format, String date) {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat(format);
                return (int) (sdf.parse(date).getTime() / 1000);
            } catch (Exception e) {
                return 0;
            }
        }

        public static int getSecondByDateStr(String date) {
            return getSecondByDateStr(FMT_DATE_TIME, date);
        }

        public static int getPvPSecondByDateStr(String date) {
            return getSecondByDateStr(PVP_DATE, date);
        }

        public static Date str2Data(String str) throws ParseException {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.parse(str);
        }

        public static long str2Long(String str) {
            try {
                return str2Data(str).getTime();
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return 0;
        }
    }

    public static byte[] objToByte(Object object) {
        byte[] resData = null;
        ObjectOutputStream ot = null;
        try {
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            ot = new ObjectOutputStream(outStream);
            ot.writeObject(object);

            resData = outStream.toByteArray();
        } catch (IOException e) {
            log.error("", e);
        } finally {
            if (ot != null) {
                try {
                    ot.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }
        return resData;
    }

    public static Object byteToObj(byte[] data) {
        Object obj = null;
        ObjectInputStream in = null;
        try {
            in = new ObjectInputStream(new ByteArrayInputStream(data));
            obj = in.readObject();
        } catch (Exception e) {
            log.error("", e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }
        return obj;
    }

    public static int getCostCrystal(int cdTime) {
        if (cdTime == 0) {
            return 0;
        }

        // 将秒转成分钟
        int minute = (cdTime / 60);

        // 不足一分钟按照一分钟计算
        if (cdTime % 60 != 0) {
            minute += 1;
        }

        // 每分钟消耗一个钻石
        return minute;
    }

    public static int randomInt(int begin, int end) {
        return random.nextInt((end - begin) + 1) + begin;
    }

    public static int randomOne2N(int n) {
        return random.nextInt(n) + 1;
    }

    public static int randomOneN(int n) {
        return random.nextInt(n);
    }

    public static int randomM2N(int m, int n) {
        if (m >= n) {
            throw new RuntimeException("m must < n ......");
        }
        int result = random.nextInt(n - m + 1) + m;
        if (result < m) {
            result = m;
        }
        if (result > n) {
            result = n;
        }
        return result;
    }

    /*
     * byte[] 转 int
     * @param bs, byte数组源
     * @param start, 数组起始位置
     * @param len, 截取长度
     */
    public static int getIntByBytes(byte[] bs, int start, int len) {
        int ret = 0;
        int tmp;
        for (int i = start, length = start + len; i < length; i++) {
            tmp = ((int) bs[i]) & 0xff;
            tmp <<= i * 8;
            ret += tmp;
        }

        return ret;
    }

    public static class BagUtils {

        /**
         * 根据全局孔转换得出背包
         * 
         * @param hole
         * @return
         */
        public static int getBag(int hole) {
            return hole >> 12;
        }

        /**
         * 根据全局孔转换出背包中孔的位置
         * 
         * @param hole
         * @return
         */
        public static int getBagHole(int hole) {
            return hole & 0xFFF;
        }

        /**
         * 通过背包和背包中的孔位获取全局唯一的孔编号
         * 
         * @param bag
         * @param bagHole
         * @return
         */
        public static int getGlobleHole(int bag, int bagHole) {
            return (bag << 12) | bagHole;
        }

        /**
         * 修正道具堆叠数值
         * 
         * @param pile
         * @return
         */
        public static int repairPile(int pile) {
            if (pile == 0) {
                return 1;
            }
            if (pile == -1) {
                return Integer.MAX_VALUE;
            }
            return pile;
        }
    }


    /**
     * 参数转换
     * 
     * @param paramMap
     * @return
     */
    public static IoBuffer encodeParam(Map<String, String> paramMap) {
        IoBuffer buf = IoBuffer.allocate(4 * 1024);
        buf.order(ByteOrder.BIG_ENDIAN);
        String packSize = paramMap.size() + "";
        buf.putInt(packSize.getBytes().length);
        buf.put(packSize.getBytes());
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();

            String param = key + "=" + value;
            short paramLen = (short) param.getBytes().length;
            buf.putShort(paramLen);
            buf.put(param.getBytes());
        }
        buf.flip();
        return buf;
    }

    /**
     * URL字符串反解析(两次URLDecode)
     * 
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     */
    public static Map<String, String> parseFromURLStr(String str) throws Exception {
        Map<String, String> paramMap = new HashMap<String, String>();
        String params = URLDecoder.decode(str, GameServerConstants.DEFAULT_CHARSET);
        String[] entry = params.split("&");
        for (String strKv : entry) {
            String[] kv = strKv.split("=");
            String key = kv[0];
            String value = "";
            if (kv.length > 1) {
                value = URLDecoder.decode(kv[1], GameServerConstants.DEFAULT_CHARSET);
            }
            paramMap.put(key, value);
        }
        return paramMap;
    }

    public static String getStringWithLength(String str, int length) {
        if (null == str)
            return "";
        if (str.length() > length) {
            return str.substring(0, length);
        } else {
            return str;
        }
    }

    public static <T> T getSessionAttr(IoSession session, Object key) {
        return (T) session.getAttribute(key);
    }

}
